package com.actionpals.net
{
	import flash.events.AsyncErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.SecurityErrorEvent;
	import flash.events.StatusEvent;
	import flash.net.LocalConnection;
	
	public class LocalConnector extends EventDispatcher
	{
		protected var genericConn:LocalConnection;
		protected var sendConn:LocalConnection;
		protected var receiveConn:LocalConnection;
		protected var genericChannel:String;
		protected var sendingChannel:String;
		protected var receivingChannel:String;
		protected var client:Object;
		
		public function LocalConnector( channel:String, client:Object )
		{
			this.genericChannel = channel;
			this.client = client;
			
			init();
		}
		
		protected function init():void
		{
			genericConn = new LocalConnection();
			genericConn.client = this;
			genericConn.allowDomain();
			genericConn.addEventListener( StatusEvent.STATUS, onGenericStatus );
			genericConn.addEventListener( AsyncErrorEvent.ASYNC_ERROR, onGenericAsyncError );
			genericConn.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onGenericSecurityError );
			
			sendConn = new LocalConnection();
			sendConn.addEventListener( StatusEvent.STATUS, onSendStatus );
			sendConn.addEventListener( AsyncErrorEvent.ASYNC_ERROR, onSendAsyncError );
			sendConn.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSendSecurityError );
			
			receiveConn = new LocalConnection();
			receiveConn.client = this.client;
			receiveConn.allowDomain( "*" );
			
			sendHandshake();
		}
		
		protected function sendHandshake():void
		{			
			try
			{
				sendConn.send( this.genericChannel, "receiveHandshake", this.receivingChannel );
			}
			catch( error:Error )
			{
				
			}
		}
		
		public function receiveHandshake( channel:String ):void
		{
			this.sendingChannel = channel;
			
			receiveConn.client = this.client;
			receiveConn.connect( this.receivingChannel );
			
			sendHandshake();
			dispatchEvent( new Event( Event.CONNECT, false, false ) );
		}
		
		protected function confirmHandshake():void
		{		
			try
			{
				sendConn.send( this.genericChannel, "recieveConfirmation", this.receivingChannel );
			}
			catch( error:Error )
			{
				trace( error );
			}
		}
		
		public function recieveConfirmation( channel:String ):void
		{
			receiveConn.connect( channel );
			destroyGenericConn();
			dispatchEvent( new Event( Event.CONNECT, false, false ) );
		}		
		
		protected function getUniqueChannel():String
		{
			return "_" + Math.round( Math.random() * int.MAX_VALUE ).toString();
		}
		
		protected function destroyGenericConn():void
		{
			genericConn.removeEventListener( StatusEvent.STATUS, onGenericStatus );
			genericConn.removeEventListener( AsyncErrorEvent.ASYNC_ERROR, onGenericAsyncError );
			genericConn.removeEventListener( SecurityErrorEvent.SECURITY_ERROR, onGenericSecurityError );
			genericConn = null;
		}
		
		protected function onGenericStatus( event:StatusEvent ):void
		{
			var level:String = event.level;
			var channel:String = ( level == "error" ) ? this.genericChannel : this.receivingChannel;
			
			genericConn.connect( channel );
		}
		
		protected function onGenericAsyncError( event:AsyncErrorEvent ):void
		{
			
		}
		
		protected function onGenericSecurityError( event:SecurityErrorEvent ):void
		{
			
		}
		
		protected function onSendStatus( event:StatusEvent ):void
		{
			
		}
		
		protected function onSendAsyncError( event:AsyncErrorEvent ):void
		{
			
		}
		
		protected function onSendSecurityError( event:SecurityErrorEvent ):void
		{
			
		}
	}
}